import Module from './Module';
import $ from 'jquery';

export default class Util extends Module {

	_init() {
		this.editor = this._module;
		if (this.browser.msie && this.browser.version < 11) {
			return this.phBr = '';
		}
	}

	reflow(el) {
		if (el == null) {
			el = document;
		}
		return $(el)[0].offsetHeight;
	}

	metaKey(e) {
		let isMac;
		isMac = /Mac/.test(navigator.userAgent);
		if (isMac) {
			return e.metaKey;
		} else {
			return e.ctrlKey;
		}
	}

	isEmptyNode(node) {
		let $node;
		$node = $(node);
		return $node.is(':empty') || (!$node.text() && !$node.find(':not(br, span, div)').length);
	}

	isDecoratedNode(node) {
		return $(node).is('[class^="simditor-"]');
	}

	isBlockNode(node) {
		node = $(node)[0];
		if (!node || node.nodeType === 3) {
			return false;
		}
		return new RegExp(`^(${this.blockNodes.join('|')})$`).test(node.nodeName.toLowerCase());
	}

	getNodeLength(node) {
		node = $(node)[0];
		switch (node.nodeType) {
			case 7:
			case 10:
				return 0;
			case 3:
			case 8:
				return node.length;
			default:
				return node.childNodes.length;
		}
	}

	dataURLtoBlob(dataURL) {
		let BlobBuilder;
		let arrayBuffer;
		let bb;
		let blobArray;
		let byteString;
		let hasArrayBufferViewSupport;
		let hasBlobConstructor;
		let i;
		let intArray;
		let k;
		let mimeString;
		let ref;
		let supportBlob;
		hasBlobConstructor = window.Blob && ((() => {
			try {
				return Boolean(new Blob());
			} catch (_error) {
				return false;
			}
		}))();
		hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array && ((() => {
			try {
				return new Blob([new Uint8Array(100)]).size === 100;
			} catch (_error) {
				return false;
			}
		}))();
		BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
		supportBlob = hasBlobConstructor || BlobBuilder;
		if (!(supportBlob && window.atob && window.ArrayBuffer && window.Uint8Array)) {
			return false;
		}
		if (dataURL.split(',')[0].includes('base64')) {
			byteString = atob(dataURL.split(',')[1]);
		} else {
			byteString = decodeURIComponent(dataURL.split(',')[1]);
		}
		arrayBuffer = new ArrayBuffer(byteString.length);
		intArray = new Uint8Array(arrayBuffer);
		for (i = k = 0, ref = byteString.length; 0 <= ref ? k <= ref : k >= ref; i = 0 <= ref ? ++k : --k) {
			intArray[i] = byteString.charCodeAt(i);
		}
		mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0];
		if (hasBlobConstructor) {
			blobArray = hasArrayBufferViewSupport ? intArray : arrayBuffer;
			return new Blob([blobArray], {
				type: mimeString
			});
		}
		bb = new BlobBuilder();
		bb.append(arrayBuffer);
		return bb.getBlob(mimeString);
	}

	throttle(func, wait) {
		let args;
		let call;
		let ctx;
		let last;
		let rtn;
		let throttled;
		let timeoutID;
		last = 0;
		timeoutID = 0;
		ctx = args = rtn = null;
		call = () => {
			timeoutID = 0;
			last = +new Date();
			rtn = func.apply(ctx, args);
			ctx = null;
			return args = null;
		};
		throttled = function () {
			let delta;
			ctx = this;
			args = arguments;
			delta = new Date() - last;
			if (!timeoutID) {
				if (delta >= wait) {
					call();
				} else {
					timeoutID = setTimeout(call, wait - delta);
				}
			}
			return rtn;
		};
		throttled.clear = () => {
			if (!timeoutID) {
				return;
			}
			clearTimeout(timeoutID);
			return call();
		};
		return throttled;
	}

	formatHTML(html) {
		let cursor;
		let indentString;
		let lastMatch;
		let level;
		let match;
		let re;
		let repeatString;
		let result;
		let str;
		re = /<(\/?)(.+?)(\/?)>/g;
		result = '';
		level = 0;
		lastMatch = null;
		indentString = '  ';
		repeatString = (str, n) => new Array(n + 1).join(str);
		while ((match = re.exec(html)) !== null) {
			match.isBlockNode = $.inArray(match[2], this.blockNodes) > -1;
			match.isStartTag = match[1] !== '/' && match[3] !== '/';
			match.isEndTag = match[1] === '/' || match[3] === '/';
			cursor = lastMatch ? lastMatch.index + lastMatch[0].length : 0;
			if ((str = html.substring(cursor, match.index)).length > 0 && $.trim(str)) {
				result += str;
			}
			if (match.isBlockNode && match.isEndTag && !match.isStartTag) {
				level -= 1;
			}
			if (match.isBlockNode && match.isStartTag) {
				if (!(lastMatch && lastMatch.isBlockNode && lastMatch.isEndTag)) {
					result += '\n';
				}
				result += repeatString(indentString, level);
			}
			result += match[0];
			if (match.isBlockNode && match.isEndTag) {
				result += '\n';
			}
			if (match.isBlockNode && match.isStartTag) {
				level += 1;
			}
			lastMatch = match;
		}
		return $.trim(result);
	}
}

Util.pluginName = 'Util';
Util.prototype.phBr = '<br/>';
Util.prototype.os = ((() => {
	let os;
	os = {};
	if (/Mac/.test(navigator.appVersion)) {
		os.mac = true;
	} else if (/Linux/.test(navigator.appVersion)) {
		os.linux = true;
	} else if (/Win/.test(navigator.appVersion)) {
		os.win = true;
	} else if (/X11/.test(navigator.appVersion)) {
		os.unix = true;
	}
	if (/Mobi/.test(navigator.appVersion)) {
		os.mobile = true;
	}
	return os;
}))();
Util.prototype.browser = ((() => {
	let chrome;
	let edge;
	let firefox;
	let ie;
	let ref;
	let ref1;
	let ref2;
	let ref3;
	let ref4;
	let safari;
	let ua;
	ua = navigator.userAgent;
	ie = /(msie|trident)/i.test(ua);
	chrome = /chrome|crios/i.test(ua);
	safari = /safari/i.test(ua) && !chrome;
	firefox = /firefox/i.test(ua);
	edge = /edge/i.test(ua);
	if (ie) {
		return {
			msie: true,
			version: ((ref = ua.match(/(msie |rv:)(\d+(\.\d+)?)/i)) != null ? ref[2] : void 0) * 1
		};
	} else if (edge) {
		return {
			edge: true,
			webkit: true,
			version: ((ref1 = ua.match(/edge\/(\d+(\.\d+)?)/i)) != null ? ref1[1] : void 0) * 1
		};
	} else if (chrome) {
		return {
			webkit: true,
			chrome: true,
			version: ((ref2 = ua.match(/(?:chrome|crios)\/(\d+(\.\d+)?)/i)) != null ? ref2[1] : void 0) * 1
		};
	} else if (safari) {
		return {
			webkit: true,
			safari: true,
			version: ((ref3 = ua.match(/version\/(\d+(\.\d+)?)/i)) != null ? ref3[1] : void 0) * 1
		};
	} else if (firefox) {
		return {
			mozilla: true,
			firefox: true,
			version: ((ref4 = ua.match(/firefox\/(\d+(\.\d+)?)/i)) != null ? ref4[1] : void 0) * 1
		};
	} else {
		return {};
	}
}))();
Util.prototype.support = ((() => ({
	onselectionchange: ((() => {
		let e;
		let onselectionchange;
		onselectionchange = document.onselectionchange;
		if (onselectionchange !== void 0) {
			try {
				document.onselectionchange = 0;
				return document.onselectionchange === null;
			} catch (_error) {
				e = _error;
			} finally {
				document.onselectionchange = onselectionchange;
			}
		}
		return false;
	}))(),

	oninput: ((() => !/(msie|trident)/i.test(navigator.userAgent)))()
})))();
Util.prototype.blockNodes = ["div", "p", "ul", "ol", "li", "blockquote", "hr", "pre", "h1", "h2", "h3", "h4", "h5", "table"];
